home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
screen32.lha
/
screen-3.2b
/
mark.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-02
|
25KB
|
1,145 lines
/* Copyright (c) 1991
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Copyright (c) 1987 Oliver Laumann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING); if not, write to the
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Noteworthy contributors to screen's design and implementation:
* Wayne Davison (davison@borland.com)
* Patrick Wolfe (pat@kai.com, kailand!pat)
* Bart Schaefer (schaefer@cse.ogi.edu)
* Nathan Glasser (nathan@brokaw.lcs.mit.edu)
* Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
* Howard Chu (hyc@hanauma.jpl.nasa.gov)
* Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
* Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
* Marc Boucher (marc@CAM.ORG)
*
****************************************************************
*/
#ifndef lint
static char rcs_id[] = "$Id: mark.c,v 1.2 92/02/03 02:27:48 jnweiger Exp $ FAU";
#endif
#include <sys/types.h>
#ifdef BSD
# include <sys/signal.h>
#endif /* BSDI */
#include "config.h"
#include "screen.h"
#include "ansi.h" /* here we find A_SO, ASCII, EXPENSIVE */
#include "extern.h"
static int is_letter __P((int));
static void nextword __P((int *, int *, int, int));
static int linestart __P((int));
static int lineend __P((int));
static int rem __P((int, int , int , int , int , char *, int));
static int eq __P((int, int ));
static void revto __P((int, int));
static void revto_line __P((int, int, int));
static void MarkRedisplayLine __P((int, int, int, int));
static int MarkRewrite __P((int, int, int, int));
static void process_mark_input __P((char **, int *));
static void AbortMarkRoutine __P((void));
static int MarkScrollDownDisplay __P((int));
static int MarkScrollUpDisplay __P((int));
int join_with_cr = 0;
extern struct win *fore, *wtab[];
extern int screenwidth, screenheight;
extern int screentop, screenbot;
extern char GlobalAttr, GlobalCharset;
extern int in_ovl;
extern int HS;
extern int LP;
extern char *null, *blank;
#ifdef NETHACK
extern nethackflag;
#endif
char *copybuffer = NULL;
int copylen = 0;
char mark_key_tab[256]; /* this array must be initialised first! */
static int in_mark; /* mark routine active */
static int left_mar, right_mar, nonl;
static int x1, y1, second; /* y1 is in terms of WIN coordinates, not DISPLAY */
static int cx, cy; /* Cursor Position in WIN coords*/
static rep_cnt; /* no. of repeats are rep_cnt+1. jw. */
static int append_mode; /* shall we overwrite or append to copybuffer */
static write_buffer; /* shall we do a KEY_WRITE_EXCHANGE right away? */
static hist_offset;
static int is_letter(c)
char c;
{
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_' || c == '.' ||
c == '@' || c == ':' ||
c == '%' || c == '!' ||
c == '-' || c == '+')
/* thus we can catch email-addresses as a word :-) */
return 1;
else if (c != ' ')
return 2;
return 0;
}
/*
* iWIN gives us a reference to line y of the *whole* image
* where line 0 is the oldest line in our history.
* y must be in WIN coordinate system, not in display.
*/
#define iWIN(y) ((y < fore->histheight) ? fore->ihist[(fore->histidx + y)\
% fore->histheight] : fore->image[y - fore->histheight])
#define aWIN(y) ((y < fore->histheight) ? fore->ahist[(fore->histidx + y)\
% fore->histheight] : fore->attr[y - fore->histheight])
#define fWIN(y) ((y < fore->histheight) ? fore->fhist[(fore->histidx + y)\
% fore->histheight] : fore->font[y - fore->histheight])
/*
* hist_offset tells us, how many lines there are on top of the
* visible screen.
*/
#define W2D(y) ((y)-hist_offset)
#define D2W(y) ((y)+hist_offset)
static int
linestart(y)
int y;
{
register int x;
register char *i;
for (x = left_mar, i = iWIN(y) + x; x < screenwidth-1; x++)
if (*i++ != ' ')
break;
if (x == screenwidth-1)
x = left_mar;
return(x);
}
static int
lineend(y)
int y;
{
register int x;
register char *i;
for (x = right_mar, i = iWIN(y) + x; x >= 0; x--)
if (*i-- != ' ')
break;
if (x < 0)
x = left_mar;
return(x);
}
/*
* nextword calculates the cursor position of the num'th word.
* If the cursor is on a word, it counts as the first.
* NW_BACK: search backward
* NW_ENDOFWORD: find the end of the word
* NW_MUSTMOVE: move even if the position is correct.
*/
#define NW_BACK 1
#define NW_ENDOFWORD 2
#define NW_MUSTMOVE 4
static void
nextword(xp, yp, flags, num)
int *xp, *yp, flags, num;
{
int xx = screenwidth, yy = fore->histheight + screenheight;
register int sx, oq, q, x, y;
x = *xp;
y = *yp;
sx = (flags & NW_BACK) ? -1 : 1;
if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE))
x += sx;
for (oq = -1; ; x += sx, oq = q)
{
if (x >= xx || x < 0)
q = 0;
else
q = is_letter(iWIN(y)[x]);
if (oq >= 0 && oq != q)
{
if (oq == 0 || !(flags & NW_ENDOFWORD))
*xp = x;
else
*xp = x-sx;
*yp = y;
if ((!(flags & NW_ENDOFWORD) && q) ||
((flags & NW_ENDOFWORD) && oq))
{
if (--num <= 0)
return;
}
}
if (x == xx)
{
x = -1;
if (++y >= yy)
return;
}
else if (x < 0)
{
x = xx;
if (--y < 0)
return;
}
}
}
/*
* y1, y2 are WIN coordinates
*
* redisplay: 0 - just copy
* 1 - redisplay + copy
* 2 - count + copy, don't redisplay
*/
static int rem(x1, y1, x2, y2, redisplay, pt, yend)
int x1, y1, x2, y2, redisplay, yend;
char *pt;
{
int i, j, from, to, ry;
int l = 0;
char *im;
second = 0;
if (y2 < y1 || ((y2 == y1) && (x2 < x1)))
{
i = y2;
y2 = y1;
y1 = i;
i = x2;
x2 = x1;
x1 = i;
}
ry = y1 - hist_offset;
i = y1;
if (redisplay != 2 && pt == 0 && ry <0)
{
i -= ry;
ry = 0;
}
for (; i <= y2; i++, ry++)
{
if (redisplay != 2 && pt == 0 && ry > yend)
break;
from = (i == y1) ? x1 : 0;
if (from < left_mar)
from = left_mar;
for (to = screenwidth-1, im = iWIN(i)+to; to>=0; to--)
if (*im-- != ' ')
break;
if (i == y2 && x2 < to)
to = x2;
if (to > right_mar)
to = right_mar;
if (redisplay == 1 && from <= to && ry >=0 && ry <= yend)
MarkRedisplayLine(ry, from, to, 0);
if (redisplay != 2 && pt == 0) /* don't count/copy */
continue;
for (j = from, im = iWIN(i)+from; j <= to; j++)
{
if (pt)
*pt++ = *im++;
l++;
}
if (i != y2)
{
/*
* this code defines, what glues lines together
*/
switch (nonl)
{
case 0: /* lines separated by newlines */
if (join_with_cr)
{
if (pt)
*pt++ = '\r';
l++;
}
if (pt)
*pt++ = '\n';
l++;
break;
case 1: /* nothing to separate lines */
break;
case 2: /* lines separated by blanks */
if (pt)
*pt++ = ' ';
l++;
break;
}
}
}
return(l);
}
static int eq(a, b)
int a, b;
{
if (a == b)
return 1;
if (a == 0 || b == 0)
return 1;
if (a <= '9' && a >= '0' && b <= '9' && b >= '0')
return 1;
return 0;
}
static int crazychar = 0;
static int crazy_y = -1;
static int crazy_x = -1;
int MarkRoutine(flag) /* return value 1 when copybuffer changed; */
int flag;
{
int x, y, i;
hist_offset = fore->histheight;
if (!fore->active)
{
Msg(0, "Fore window is not active !!!");
return 0;
}
second = 0;
rep_cnt = 0;
append_mode = 0;
write_buffer = 0;
nonl = left_mar = 0;
right_mar = screenwidth-1;
x = fore->x;
y = D2W(fore->y);
if (x >= screenwidth)
x = screenwidth-1;
if (flag == CRAZY && crazychar != 0 && crazy_x != -1 && crazy_y != -1)
{
Msg(0, "CRAZY mode not impl.\n");
}
crazychar = 0;
crazy_y = -1;
crazy_x = -1;
if (flag == TRICKY)
{
int f, q = 0, xx, yy;
char *linep;
debug2("cursor is at x=%d, y=%d\n", fore->x, D2W(fore->y));
for (xx = fore->x - 1, linep = iWIN(y) + xx; xx >= 0; xx--)
if ((q = *linep--) != ' ' )
break;
debug3("%c at (%d,%d)\n", q, xx, y);
for (yy = D2W(fore->y) - 1; yy >= 0; yy--)
if (xx < 0 || eq(iWIN(yy)[xx], q))
{ /* line is matching... */
f = 0;
for (i = fore->x; i < screenwidth-1; i++)
{
if (iWIN(yy)[i] != ' ')
{
f = 1;
break;
}
}
if (f)
break;
}
if (yy < 0)
return 0;
xx = 0;
for (i = screenwidth-1, linep = iWIN(yy)+i; i>0; i--)
if (*linep-- != ' ')
break;
if (i < x)
i = x;
if (copybuffer != NULL)
Free(copybuffer);
if ((copybuffer = malloc((unsigned) (i - x + 2))) == NULL)
{
Msg(0, "Not enough memoooh!... Sorry.");
return 0;
}
rem(x, yy, i, yy, 0, copybuffer, 0);
copylen = i - x + 1;
return 1;
}
InitOverlayPage(process_mark_input, MarkRedisplayLine, MarkRewrite, 1);
GotoPos(x, W2D(y));
#ifdef NETHACK
if (nethackflag)
Msg(0, "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)",
x+1, W2D(y+1), fore->histheight, fore->width, fore->height);
else
#endif
Msg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
x+1, W2D(y+1), fore->histheight, fore->width, fore->height);
fflush(stdout);
cx = x1 = x;
cy = y1 = y;
in_mark = 1;
return 0;
}
static void process_mark_input(inbufp,inlenp)
char **inbufp;
int *inlenp;
{
char *inbuf, *pt;
int inlen;
int x2, y2, i, j, yend;
int newcopylen = 0, od;
/*
char *extrap = 0, extrabuf[100];
*/
if (inbufp == 0)
{
AbortMarkRoutine();
return;
}
inbuf= *inbufp;
inlen= *inlenp;
pt = inbuf;
while (in_mark && (inlen /* || extrap */))
{
if (!HS)
RemoveStatus();
/*
if (extrap)
{
od = *extrap++;
if (*extrap == 0)
extrap = 0;
}
else
*/
{
od = mark_key_tab[*pt++];
inlen--;
}
if (od >= '0' && od <= '9')
{
if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0))
{
rep_cnt = 10 * rep_cnt + od - '0';
continue;
/*
* Now what is that 1001 here? Well, we have a screen with
* 25 * 80 = 2000 characters. Movement is at most across the full
* screen. This we do with word by word movement, as character by
* character movement never steps over line boundaries. The most words
* we can place on the screen are 1000 single letter words. Thus 1001
* is sufficient. Users with bigger screens never write in single letter
* words, as they should be more advanced. jw.
* Oh, wrong. We still give even the experienced user a factor of ten.
*/
}
}
switch (od)
{
case '\014': /* CTRL-L Redisplay */
Redisplay(0);
GotoPos(cx, W2D(cy));
break;
case '\010': /* CTRL-H Backspace */
case 'h':
if (rep_cnt == 0)
rep_cnt = 1;
revto(cx - rep_cnt, cy);
break;
case '\016': /* CTRL-N */
case 'j':
if (rep_cnt == 0)
rep_cnt = 1;
revto(cx, cy + rep_cnt);
break;
case '+':
if (rep_cnt == 0)
rep_cnt = 1;
j = cy + rep_cnt;
if (j > fore->histheight + screenheight - 1)
j = fore->histheight + screenheight - 1;
revto(linestart(j), j);
break;
case '-':
if (rep_cnt == 0)
rep_cnt = 1;
j = cy - rep_cnt;
if (j < 0)
j = 0;
revto(linestart(j), j);
break;
case '^':
revto(linestart(cy), cy);
break;
case '\n':
revto(left_mar, cy + 1);
break;
case 'k':
case '\020': /* CTRL-P */
if (rep_cnt == 0)
rep_cnt = 1;
revto(cx, cy - rep_cnt);
break;
case 'l':
if (rep_cnt == 0)
rep_cnt = 1;
revto(cx + rep_cnt, cy);
break;
case '\001': /* CTRL-A from tcsh/emacs */
case '0':
revto(left_mar, cy);
break;
case '\004': /* CTRL-D down half screen */
if (rep_cnt == 0)
rep_cnt = (screenheight+1) >> 1;
revto_line(cx, cy + rep_cnt, W2D(cy));
break;
case '$':
revto(lineend(cy), cy);
break;
case '\025': /* CTRL-U up half screen */
if (rep_cnt == 0)
rep_cnt = (screenheight+1) >> 1;
revto_line(cx, cy - rep_cnt, W2D(cy));
break;
case '?':
if (left_mar == 0 && right_mar == screenwidth - 1)
Msg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1,
hist_offset);
else
Msg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1,
left_mar+1, right_mar+1, W2D(cy)+1, hist_offset);
break;
case '\002': /* CTRL-B back one page */
if (rep_cnt == 0)
rep_cnt = 1;
rep_cnt *= (screenheight-1);
revto(cx, cy - rep_cnt);
break;
case '\006': /* CTRL-F forward one page */
if (rep_cnt == 0)
rep_cnt = 1;
rep_cnt *= (screenheight-1);
revto(cx, cy + rep_cnt);
break;
case '\005': /* CTRL-E scroll up */
if (rep_cnt == 0)
rep_cnt = 1;
rep_cnt = MarkScrollUpDisplay(rep_cnt);
if (cy < D2W(0))
revto(cx, D2W(0));
else
GotoPos(cx, W2D(cy));
break;
case '\031': /* CTRL-Y scroll down */
if (rep_cnt == 0)
rep_cnt = 1;
rep_cnt = MarkScrollDownDisplay(rep_cnt);
if (cy > D2W(screenheight-1))
revto(cx, D2W(screenheight-1));
else
GotoPos(cx, W2D(cy));
break;
case '@':
/* it may be usefull to have a key that does nothing */
break;
case '%':
rep_cnt--;
/* rep_cnt is a percentage for the history buffer */
if (rep_cnt < 0)
rep_cnt = 0;
if (rep_cnt > 100)
rep_cnt = 100;
revto_line(left_mar, (rep_cnt * (fore->histheight + screenheight)) / 100, (screenheight-1)/2);
break;
case 'g':
rep_cnt = 1;
/* FALLTHROUGH */
case 'G':
/* rep_cnt is here the WIN line number */
if (rep_cnt == 0)
rep_cnt = fore->histheight + screenheight;
revto_line(left_mar, --rep_cnt, (screenheight-1)/2);
break;
case 'H':
revto(left_mar, D2W(0));
break;
case 'M':
revto(left_mar, D2W((screenheight-1) / 2));
break;
case 'L':
revto(left_mar, D2W(screenheight-1));
break;
case '|':
revto(--rep_cnt, cy);
break;
case 'w':
i = cx;
j = cy;
if (rep_cnt == 0)
rep_cnt = 1;
nextword(&i, &j, NW_MUSTMOVE, rep_cnt);
revto(i, j);
break;
case 'e':
i = cx;
j = cy;
if (rep_cnt == 0)
rep_cnt = 1;
nextword(&i, &j, NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt);
revto(i, j);
break;
case 'b':
i = cx;
j = cy;
if (rep_cnt == 0)
rep_cnt = 1;
nextword(&i, &j, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt);
revto(i, j);
break;
case 'a':
append_mode = 1 - append_mode;
debug1("append mode %d--\n", append_mode);
Msg(0, (append_mode) ? ":set append" : ":set noappend");
break;
case 'v':
case 'V':
/* this sets start column to column 9 for VI :set nu users */
if (left_mar == 8)
rep_cnt = 1;
else
rep_cnt = 9;
/* FALLTHROUGH */
case 'c':
case 'C':
/* set start column (c) and end column (C) */
if (second)
{
rem(x1, y1, cx, cy, 1, (char *)0, screenheight-1); /* Hack */
second = 1; /* rem turns off second */
}
rep_cnt--;
if (rep_cnt < 0)
rep_cnt = cx;
if (od != 'C')
{
left_mar = rep_cnt;
if (left_mar > right_mar)
left_mar = right_mar;
}
else
{
right_mar = rep_cnt;
if (left_mar > right_mar)
right_mar = left_mar;
}
if (second)
{
int x = cx, y = cy;
cx = x1; cy = y1;
revto(x, y);
}
if (od == 'v' || od == 'V')
Msg(0, (left_mar != 8) ? ":set nonu" : ":set nu");
break;
case 'J':
/* how do you join lines in VI ? */
nonl = (nonl + 1) % 3;
switch (nonl)
{
case 0:
if (join_with_cr)
Msg(0, "Multiple lines (CR/LF)");
else
Msg(0, "Multiple lines (LF)");
break;
case 1:
Msg(0, "Lines joined");
break;
case 2:
Msg(0, "Lines joined with blanks");
break;
}
break;
case 'y':
case 'Y':
if (!second)
{
revto(linestart(cy), cy);
second++;
x1 = cx;
y1 = cy;
}
if (--rep_cnt > 0)
revto(cx, cy + rep_cnt);
revto(lineend(cy), cy);
if (od == 'y')
break;
/* FALLTHROUGH */
case 'W':
if (od == 'W')
{
if (rep_cnt == 0)
rep_cnt = 1;
if (!second)
{
i = cx;
j = cy;
nextword(&i, &j, NW_BACK|NW_ENDOFWORD, 1);
revto(i, j);
second++;
x1 = cx;
y1 = cy;
}
i = cx;
j = cy;
nextword(&i, &j, NW_ENDOFWORD, rep_cnt);
revto(i, j);
}
/* FALLTHROUGH */
case 'A':
if (od == 'A')
append_mode = 1;
/* FALLTHROUGH */
case '>':
if (od == '>')
write_buffer = 1;
/* FALLTHROUGH */
case ' ':
case '\r':
if (!second)
{
second++;
x1 = cx;
y1 = cy;
revto(x1, y1);
#ifdef NETHACK
if (nethackflag)
Msg(0, "You drop a magic marker - Column %d Line %d",
cx+1, W2D(cy)+1, hist_offset);
else
#endif
Msg(0, "First mark set - Column %d Line %d", cx+1, cy+1);
break;
}
else
{
x2 = cx;
y2 = cy;
newcopylen = rem(x1, y1, x2, y2, 2, (char *)0, 0); /* count */
if (copybuffer != NULL && !append_mode)
{
copylen = 0;
Free(copybuffer);
}
if (newcopylen > 0)
{
/* the +3 below is for : cr + lf + \0 */
if (copybuffer != NULL)
copybuffer = realloc(copybuffer,
(unsigned) (copylen + newcopylen + 3));
else
{
copylen = 0;
copybuffer = malloc((unsigned) (newcopylen + 3));
}
if (copybuffer == NULL)
{
AbortMarkRoutine();
Msg(0, "Not enough memoooh!... Sorry.");
copylen = 0;
copybuffer = NULL;
break;
}
if (append_mode)
{
switch (nonl)
/*
* this code defines, what glues lines together
*/
{
case 0:
if (join_with_cr)
{
copybuffer[copylen] = '\r';
copylen++;
}
copybuffer[copylen] = '\n';
copylen++;
break;
case 1:
break;
case 2:
copybuffer[copylen] = ' ';
copylen++;
break;
}
}
yend = screenheight - 1;
if (fore->histheight - hist_offset < screenheight)
{
second = 0;
yend -= MarkScrollUpDisplay(fore->histheight - hist_offset);
}
copylen += rem(x1, y1, x2, y2, hist_offset == fore->histheight, copybuffer + copylen, yend);
}
if (hist_offset != fore->histheight)
{
in_ovl = 0; /* So we can use Activate() */
Activate(0);
}
ExitOverlayPage();
if (append_mode)
Msg(0, "Appended %d characters to buffer",
newcopylen);
else
Msg(0, "Copied %d characters into buffer", copylen);
if (write_buffer)
WriteFile(DUMP_EXCHANGE);
in_mark = 0;
break;
}
default:
AbortMarkRoutine();
#ifdef NETHACK
if (nethackflag)
Msg(0, "You escaped the dungeon.");
else
#endif
Msg(0, "Copy mode aborted");
break;
}
rep_cnt = 0;
}
fflush(stdout);
*inbufp = pt;
*inlenp = inlen;
}
static void revto(tx, ty)
int tx, ty;
{
revto_line(tx, ty, -1);
}
/* tx, ty: WINDOW, line: DISPLAY */
static void revto_line(tx, ty, line)
int tx, ty, line;
{
int fx, fy;
int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0;
int ystart = 0, yend = screenheight-1;
int i, ry;
if (tx < 0)
tx = 0;
else if (tx > screenwidth - 1)
tx = screenwidth -1;
if (ty < 0)
ty = 0;
else if (ty > fore->histheight + screenheight - 1)
ty = fore->histheight + screenheight - 1;
fx = cx; fy = cy;
cx = tx; cy = ty;
/*debug2("revto(%d, %d, ", x1, y1);
debug2("%d, %d, ", fx, fy);
debug2("%d, %d)\n", tx, ty);*/
/*
* if we go to a position that is currently offscreen
* then scroll the screen
*/
i = 0;
if (line >= 0 && line < screenheight)
i = W2D(ty) - line;
else if (ty < hist_offset)
i = ty - hist_offset;
else if (ty > hist_offset + (screenheight-1))
i = ty-hist_offset-(screenheight-1);
if (i > 0)
yend -= MarkScrollUpDisplay(i);
else if (i < 0)
ystart += MarkScrollDownDisplay(-i);
if (second == 0)
{
GotoPos(tx, W2D(cy));
return;
}
qq = x1 + y1 * screenwidth;
ff = fx + fy * screenwidth; /* "from" offset in WIN coords */
tt = tx + ty * screenwidth; /* "to" offset in WIN coords*/
if (ff > tt)
{
st = tt; en = ff;
x = tx; y = ty;
}
else
{
st = ff; en = tt;
x = fx; y = fy;
}
if (st > qq)
{
st++;
x++;
}
if (en < qq)
en--;
if (tt > qq)
{
revst = qq; reven = tt;
}
else
{
revst = tt; reven = qq;
}
ry = y - hist_offset;
if (ry < ystart)
{
y += (ystart - ry);
x = 0;
st = y * screenwidth;
ry = ystart;
}
for (t = st; t <= en; t++, x++)
{
if (x >= screenwidth)
{
x = 0;
y++, ry++;
}
if (ry > yend)
break;
if (t == st || x == 0)
{
for (ce = screenwidth-1; ce >= 0; ce--)
if (iWIN(y)[ce] != ' ')
break;
}
if (x <= ce && x >= left_mar && x <= right_mar
&& (LP || x < screenwidth-1 || ry < screenbot))
{
GotoPos(x, W2D(y));
if (t >= revst && t <= reven)
SaveSetAttr(A_SO, ASCII);
else
SaveSetAttr(aWIN(y)[x], fWIN(y)[x]);
PUTCHAR(iWIN(y)[x]);
}
}
GotoPos(tx, W2D(cy));
}
static void AbortMarkRoutine()
{
int yend, redisp;
yend = screenheight - 1;
redisp = second;
if (fore->histheight - hist_offset < screenheight)
{
second = 0;
yend -= MarkScrollUpDisplay(fore->histheight - hist_offset);
}
if (hist_offset != fore->histheight)
{
in_ovl = 0; /* So we can use Activate() */
Activate(0); /* to do a complete redisplay */
}
else
{
rem(x1, y1, cx, cy, redisp, (char *)0, yend);
}
ExitOverlayPage();
in_mark = 0;
}
static void MarkRedisplayLine(y, xs, xe, isblank)
int y; /* NOTE: y is in DISPLAY coords system! */
int xs, xe;
int isblank;
{
int x, i, rm;
int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */
char *wi, *wa, *wf, *oldi;
InsertMode(0); /* Not done in DisplayLine() */
wi = iWIN(D2W(y));
wa = aWIN(D2W(y));
wf = fWIN(D2W(y));
oldi = isblank ? blank : null;
if (second == 0)
{
DisplayLine(oldi, null, null, wi, wa, wf, y, xs, xe);
return;
}
sta = y1 * screenwidth + x1;
sto = cy * screenwidth + cx;
if (sta > sto)
{
i=sta; sta=sto; sto=i;
}
cp = D2W(y) * screenwidth + xs;
rm = right_mar;
for (x = screenwidth - 1; x >= 0; x--)
if (wi[x] != ' ')
break;
if (x < rm)
rm = x;
for (x = xs; x <= xe; x++, cp++)
if (cp >= sta && x >= left_mar)
break;
if (x > xs)
DisplayLine(oldi, null, null, wi, wa, wf, y, xs, x-1);
for (; x <= xe; x++, cp++)
{
if (cp > sto || x > rm || (!LP && x >= screenwidth-1 && y == screenbot))
break;
GotoPos(x, y);
SaveSetAttr(A_SO, ASCII);
PUTCHAR(wi[x]);
}
if (x<=xe)
DisplayLine(oldi, null, null, wi, wa, wf, y, x, xe);
}
static int
MarkRewrite(ry, xs, xe, doit)
int ry, xs, xe, doit;
{
int dx, x, y, st, en, t, rm;
char *a, *f, *i;
y = D2W(ry);
dx = xe - xs;
if (doit)
{
i = iWIN(y) + xs;
while (dx--)
PUTCHAR(*i++);
return(0);
}
a = aWIN(y) + xs,
f = fWIN(y) + xs;
if (second == 0)
st = en = -1;
else
{
st = y1 * screenwidth + x1;
en = cy * screenwidth + cx;
if (st > en)
{
t = st; st = en; en = t;
}
}
t = y * screenwidth + xs;
for (rm=screenwidth-1, i=iWIN(y) + screenwidth-1; rm>=0; rm--)
if (*i-- != ' ')
break;
if (rm > right_mar)
rm = right_mar;
x = xs;
while (dx--)
{
if (t >= st && t <= en && x >= left_mar && x <= rm)
{
if (GlobalAttr != A_SO || GlobalCharset != ASCII)
return(EXPENSIVE);
}
else
{
if (GlobalAttr != *a || GlobalCharset != *f)
return(EXPENSIVE);
}
a++, f++, t++, x++;
}
return(xe - xs);
}
/*
* scroll the screen contents up/down.
*/
static int MarkScrollUpDisplay(n)
int n;
{
int i;
debug1("MarkScrollUpDisplay(%d)\n", n);
if (n <= 0)
return 0;
if (n > fore->histheight - hist_offset)
n = fore->histheight - hist_offset;
i = (n < screenheight) ? n : (screenheight);
ScrollRegion(0, screenheight - 1, i);
hist_offset += n;
while (i-- > 0)
MarkRedisplayLine(screenheight-i-1, 0, screenwidth-1, 1);
return n;
}
static int MarkScrollDownDisplay(n)
int n;
{
int i;
debug1("MarkScrollDownDisplay(%d)\n", n);
if (n <= 0)
return 0;
if (n > hist_offset)
n = hist_offset;
i = (n < screenheight) ? n : (screenheight);
ScrollRegion(0, screenheight - 1, -i);
hist_offset -= n;
while (i-- > 0)
MarkRedisplayLine(i, 0, screenwidth-1, 1);
return n;
}